﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using PostProcGUI.Model.PostProcOtherGroup.Calc;
using PostProcGUI.Model.PostProcOtherGroup.Graphic;
using PostProcGUI.Model.PostProcOtherGroup.Graphic.DirectX;
using PostProcGUI.Model.PostProcOtherGroup.Graphic.OpenGl;
using PostProcGUI.ModelView.Commands;
using PostProcGUI.ModelView.ForModel;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using PostProcGUI.Model;


namespace PostProcGUI.ModelView
{
    class MainWindowViewModel : ViewModelBase
    {
        #region Поля

        private PalleteViewModel _pallete;
        private readonly PalleteViewModel _defaultPallete;
        private readonly List<Tuple<Point, double>> _usersPoints = new List<Tuple<Point, double>>();

        private bool _isPaintBorder;
        private bool _isPaintMesh;
        private bool _isPaintScale;
        private bool _isPaintData;

        private IBasis _basis;
        private IMesh _mesh;
        private IGraphic _graphic;

        private RelayCommand _changePalleteCommand;
        private RelayCommand _loadMeshCommand;
        private RelayCommand _loadDataCommand;
        private RelayCommand _savePictureCommand;
        private RelayCommand _saveDataCommand;
        private RelayCommand _savePalleteCommand;
        private RelayCommand _loadPalleteCommand;
        private RelayCommand _aboutCommand;
        private RelayCommand _helpCommand;
        private RelayCommand _settingsCommand;

        #endregion // Поля

        #region Свойства

        public ObservableCollection<LogViewModel> Logs
        {
            get { return App.Logs; }
        }

        public PalleteViewModel Pallete
        {
            get { return _pallete; }
        }

        public bool IsPaintBorder
        {
            get { return _isPaintBorder; }
            set
            {
                _isPaintBorder = value;
                OnPropertyChanged("isPaintBorder");
            }
        }

        public bool IsPaintMesh
        {
            get { return _isPaintMesh; }
            set
            {
                _isPaintMesh = value;
                OnPropertyChanged("IsPaintMesh");
            }
        }

        public bool IsPaintScale
        {
            get { return _isPaintScale; }
            set
            {
                _isPaintScale = value;
                OnPropertyChanged("IsPaintScale");
            }
        }

        public bool IsPaintData
        {
            get { return _isPaintData; }
            set
            {
                _isPaintData = value;
                OnPropertyChanged("IsPaintData");
            }
        }

        #endregion // Свойства

        #region Конструкторы

        public MainWindowViewModel()
        {
          //  AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

            _defaultPallete = new PalleteViewModel("GrayPallete");
            _defaultPallete.Pallete.Add(new ColorLevelViewModel(Color.FromArgb(255,255,255,255), 0.0));
            _defaultPallete.Pallete.Add(new ColorLevelViewModel(Color.FromArgb(255,128,128,128), 0.5));
            _defaultPallete.Pallete.Add(new ColorLevelViewModel(Color.FromArgb(255,0,0,0), 1.0));
            _defaultPallete.PalleteVisibility = Visibility.Hidden;
            _pallete = _defaultPallete;

            Logs.Add(new LogViewModel("Программа запущена"));
        }

        #endregion // Конструкторы

        #region Методы

        //private static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        //{
        //    var ex = e.ExceptionObject as Exception;
        //    string info;

        //    if (ex != null)
        //    {
        //        info = string.Format("Message: {0}", ex.Message);
        //    }
        //    else
        //    {
        //        info = string.Format("Non CLS exception: Type={0}, String={1}", e.ExceptionObject.GetType(), e.ExceptionObject);
        //    }

        //    App.Logs.Add(new LogViewModel(info, LogLevel.Critical));
        //}

        #endregion /* Методы */

        #region ChangePalleteCommand

        public ICommand ChangePalleteCommand
        {
            get
            {
                if (_changePalleteCommand != null)
                    return _changePalleteCommand;
                
                _changePalleteCommand = new RelayCommand
                    (
                        param => ChangePallete()
                    );
                return _changePalleteCommand;                
            }
        }

        public void ChangePallete()
        {
            if (!Equals(_pallete.PalleteVisibility, Visibility.Visible))
            {
                _pallete.PalleteVisibility = Visibility.Visible;
            }
        }

        #endregion //ChangePalleteCommand

        #region LoadMeshCommand

        public ICommand LoadMeshCommand
        {
            get
            {
                if (_loadMeshCommand != null)
                    return _loadMeshCommand;

                _loadMeshCommand = new RelayCommand
                    (
                        param => LoadMesh()
                    );
                return _loadMeshCommand;                
            }
        }

        public void LoadMesh()
        {
            var dialog = new FolderBrowserDialog();

            if(dialog.ShowDialog() == DialogResult.OK)
            {
                _mesh = MeshFactory.CreateMesh(dialog.SelectedPath) as Mesh;
                if(Properties.Settings.Default.TypeGraphic == "DirectX")
                    _graphic = new DirectXMainClass();
                else
                    _graphic = new OpenGlMainClass();

                _graphic.Mesh = _mesh;

                Logs.Add(new LogViewModel("Сетка загружена"));
            }
        }

        #endregion //LoadMeshCommand

        #region LoadDataCommand

        public ICommand LoadDataCommand
        {
            get
            {
                if (_loadDataCommand != null)
                    return _loadDataCommand;

                _loadDataCommand = new RelayCommand
                    (
                        param => LoadData()
                    );
                return _loadDataCommand;
            }
        }

        public void LoadData()
        {
            var dialog = new OpenFileDialog();

            if (dialog.ShowDialog() == true)
            {
                using (var file = new FileStream(Path.GetFullPath(dialog.FileName), FileMode.Open))
                {
                    _basis = BasisFactory.CreateBasis(_mesh, file);
                    _graphic.Basis = _basis;
                    Logs.Add(new LogViewModel("Решение загружено"));

                }
            }
        }

        #endregion //LoadDataCommand

        #region SavePictureCommand

        public ICommand SavePictureCommand
        {
            get
            {
                if (_savePictureCommand != null)
                    return _savePictureCommand;

                _savePictureCommand = new RelayCommand
                    (
                        param => SavePicture(),
                        param => CanSavePicture
                    );
                return _savePictureCommand;
            }
        }

        public void SavePicture()
        {
            var dialog = new OpenFileDialog();

            if (dialog.ShowDialog() == true)
            {
                using (var file = new FileStream(Path.GetFullPath(dialog.FileName), FileMode.Create))
                {
                    _graphic.SaveFrame(file);

                    Logs.Add(new LogViewModel("Кадр сохранен"));
                }
            }
        }

        public bool CanSavePicture
        {
            get
            {
                if (_basis == null)
                    return false;
                return true;
            }
        }

        #endregion //SavePictureCommand

        #region SaveDataCommand

        public ICommand SaveDataCommand
        {
            get
            {
                if (_saveDataCommand != null)
                    return _saveDataCommand;

                _saveDataCommand = new RelayCommand
                    (
                        param => SaveData(),
                        param => CanSaveData
                    );
                return _saveDataCommand;
            }
        }

        public void SaveData()
        {
            var dialog = new OpenFileDialog();

            if (dialog.ShowDialog() == true)
            {
                using (var file = new FileStream(Path.GetFullPath(dialog.FileName), FileMode.Create))
                {
                    foreach (var usersPoint in _usersPoints)
                    {
                        // Сохранить в поток file весь массив usersPoints
                    }
                }
                Logs.Add(new LogViewModel("Значения сохранены"));                
            }
        }

        public bool CanSaveData
        {
            get
            {
                if (_basis == null || _usersPoints.Count == 0)
                    return false;
                return true;
            }
        }

        #endregion //SaveDataCommand

        #region SavePalleteCommand

        public ICommand SavePalleteCommand
        {
            get
            {
                if (_savePalleteCommand != null)
                    return _savePalleteCommand;

                _savePalleteCommand = new RelayCommand
                    (
                        param => SavePallete()
                    );
                return _savePalleteCommand;
            }
        }

        public void SavePallete()
        {
            var dialog = new SaveFileDialog{Filter = @"Xml Files ( *.xml) | All Files (*.*)", AddExtension=true};

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                var serializer = new XmlSerializer(typeof(PalleteViewModel));
                using (TextWriter writer = new StreamWriter(Path.GetFullPath(dialog.FileName)))
                {
                    serializer.Serialize(writer, Pallete);
                }
            }
        }

        #endregion //SavePalleteCommand

        #region LoadPalleteCommand

        public ICommand LoadPalleteCommand
        {
            get
            {
                if (_loadPalleteCommand != null)
                    return _loadPalleteCommand;

                _loadPalleteCommand = new RelayCommand
                    (
                        param => LoadPallete()
                    );
                return _loadPalleteCommand;
            }
        }

        public void LoadPallete()
        {
            var dialog = new OpenFileDialog();

            if (dialog.ShowDialog() == true)
            {

            }
        }

        #endregion //LoadPalleteCommand

        #region HelpCommand

        public ICommand HelpCommand
        {
            get
            {
                if (_helpCommand != null)
                    return _helpCommand;

                _helpCommand = new RelayCommand
                    (
                        param => Help(),
                        param => CanHelp
                    );
                return _helpCommand;
            }
        }

        public void Help()
        {
        }

        bool CanHelp
        {
            get { return false; }
        }

        #endregion //HelpCommand

        #region SettingsCommand

        public ICommand SettingsCommand
        {
            get
            {
                if (_settingsCommand != null)
                    return _settingsCommand;

                _settingsCommand = new RelayCommand
                    (
                        param => Settings(),
                        param => CanSettings
                    );
                return _settingsCommand;
            }
        }

        public void Settings()
        {
        }

        bool CanSettings
        {
            get { return false; }
        }

        #endregion //SettingsCommand

        #region AboutCommand

        public ICommand AboutCommand
        {
            get
            {
                if (_aboutCommand != null)
                    return _aboutCommand;

                _aboutCommand = new RelayCommand
                    (
                        param => About(),
                        param => CanAbout
                    );
                return _aboutCommand;
            }
        }

        public void About()
        {
        }

        bool CanAbout
        {
            get { return false; }
        }

        #endregion //AboutCommand
    }
}
